package com.heima.media.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.heima.common.Threadlocals.UserThreadLocalUtil;
import com.heima.common.dto.PageResponseResult;
import com.heima.common.dto.ResponseResult;
import com.heima.common.dto.User;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.enums.MediaEnum;
import com.heima.media.dto.ContentDto;
import com.heima.media.dto.ImageDto;
import com.heima.media.dto.WmNewsDto;
import com.heima.media.dto.WmNewsPageDto;
import com.heima.media.entity.WmNews;
import com.heima.media.entity.WmNewsMaterial;
import com.heima.media.mapper.WmNewsMapper;
import com.heima.media.service.IAuditService;
import com.heima.media.service.IWmNewsMaterialService;
import com.heima.media.service.IWmNewsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author itheima
 * @since 2022-07-01
 */
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements IWmNewsService {

    @Autowired
    private IWmNewsMaterialService newsMaterialService;

    @Autowired
    private IAuditService auditService;

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @Value("${topic.upDownTopic}")
    private String upDownTopic;


    /**
     * 查询当前自媒体用户发布自媒体文章列表
     *
     * @param dto 查询条件
     * @return
     */
    @Override
    public PageResponseResult listByPage(WmNewsPageDto dto) {
        //1.构建分页对象
        IPage<WmNews> page = new Page<>(dto.getPage(), dto.getSize());
        //2.构建查询条件
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();

        //2.1 设置文章状态
        if (ObjectUtils.isNotEmpty(dto.getStatus())) {
            queryWrapper.eq(WmNews::getStatus, dto.getStatus());
        }
        //2.2 设置频道ID
        if (ObjectUtils.isNotEmpty(dto.getChannelId())) {
            queryWrapper.eq(WmNews::getChannelId, dto.getChannelId());
        }
        //2.3 设置关键字
        if (ObjectUtils.isNotEmpty(dto.getKeyword())) {
            queryWrapper.like(WmNews::getTitle, dto.getKeyword());
        }
        //2.4 设置发布时间
        if (ObjectUtils.isNotEmpty(dto.getBeginPubDate()) && ObjectUtils.isNotEmpty(dto.getEndPubDate())) {
            queryWrapper.between(WmNews::getPublishTime, dto.getBeginPubDate(), dto.getEndPubDate());

        }
        //2.5 设置自媒体用户ID
        User user = UserThreadLocalUtil.get();
        queryWrapper.eq(WmNews::getUserId, user.getUserId());
        //2.6 设置排序
        queryWrapper.orderByDesc(WmNews::getPublishTime);

        //3.执行查询
        this.page(page, queryWrapper);

        //4.封装响应数据
        return new PageResponseResult(dto.getPage(), dto.getSize(), page.getTotal(), page.getRecords());
    }


    /**
     * 自媒体用户发布文章（提交审核）
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult submit(WmNewsDto dto) {
        //1.验证自媒体用户是否在登录状态（从ThreadLocal中获取自媒体用户信息）
        User user = UserThreadLocalUtil.get();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //2.构建自媒体文章对象WmNew，从参数dto中拷贝获取部分数据;封装一部分；执行保存
        WmNews wmNews = new WmNews();
        //2.1 设置前端提交参数
        BeanUtils.copyProperties(dto, wmNews);
        //2.2 设置自媒体用户ID；如果发布时间为空设置为当前系统时间；设置封面图片
        wmNews.setEnable(false);
        wmNews.setSubmitedTime(new Date());
        wmNews.setUserId(user.getUserId());
        if (ObjectUtils.isEmpty(wmNews.getPublishTime())) {
            wmNews.setPublishTime(new Date());
        }
        //2.3 处理封面图片属性
        handlerCoverImage(dto, wmNews);

        //2.4 执行保存自媒体文章
        this.save(wmNews);

        //3.如果是提交审核，需要存储文章跟素材关系记录
        if (!dto.getStatus().equals(MediaEnum.NEWS_SUBMIT_STATUS_DRAFT.getVal())) {
            //3.1 设置文章正文中引用素材关系
            List<ImageDto> coverImages = dto.getImages();
            saveArticleMaterialRelation(coverImages, MediaEnum.MATERIAL_TYPE_REF_TYPE_CONVERIMG.getVal(), wmNews.getId());
            //3.2 设置文章图片中引用素材关系
            List<ImageDto> conentImages = getImagesFromContent(dto.getContent());
            saveArticleMaterialRelation(conentImages, MediaEnum.MATERIAL_TYPE_REF_TYPE_CONTENTIMG.getVal(), wmNews.getId());
        }

        //TODO 4.异步对自媒体文章进行审核-由线程池中线程来进行执行
        auditService.audit(wmNews);
        return ResponseResult.okResult();
    }


    /**
     * 将文章跟素材建立关联
     *
     * @param imageDtoList 内容图片集合 或者 正文图片集合
     * @param type         0：内容引入  1：封面引用
     * @param newsId       文章ID
     */
    private void saveArticleMaterialRelation(List<ImageDto> imageDtoList, Integer type, Integer newsId) {
        int ord = 0;
        if (!CollectionUtils.isEmpty(imageDtoList)) {
            for (ImageDto imageDto : imageDtoList) {
                WmNewsMaterial wmNewsMaterial = new WmNewsMaterial();
                wmNewsMaterial.setMaterialId(imageDto.getId());
                wmNewsMaterial.setNewsId(newsId);
                wmNewsMaterial.setType(type);
                wmNewsMaterial.setOrd(ord++);
                newsMaterialService.save(wmNewsMaterial);
            }
        }
    }


    /**
     * 处理文章封面图片；文章封面类型 字段
     *
     * @param dto    0：无图    1：单图   3：三图   -1：自动
     *               自动：程序自动从正文中获取图片作为封面：如果正文图片数量大于等于3 截图前张三图片作为封面；图片数量在1-3之间截图第一张图片作为封面；如果封面图片没有，则设置为无图
     * @param wmNews
     */
    private void handlerCoverImage(WmNewsDto dto, WmNews wmNews) {
        //1.获取前端提交封面类型
        Integer type = dto.getType();
        switch (type) {
            case 0:
                //处理用户选择无图
                wmNews.setImages("");
                wmNews.setType(MediaEnum.NEWS_COVER_TYPE_NONE.getVal());
                break;
            case 1:
                //处理用户选择单图
                List<ImageDto> list = dto.getImages();
                String images = list.get(0).getUrl();
                wmNews.setImages(images);
                wmNews.setType(MediaEnum.NEWS_COVER_TYPE_ONE.getVal());
                break;
            case 3:
                //处理用户选择三图
                List<ImageDto> images1 = dto.getImages();
                String collect = images1.stream().map(ImageDto::getUrl).collect(Collectors.joining(","));
                wmNews.setImages(collect);
                wmNews.setType(MediaEnum.NEWS_COVER_TYPE_MANY.getVal());
                break;
            default:
                //处理用户选择自动
                //1.获取文章中正文中图片，判断图片数量  -1
                List<ImageDto> contentImages = getImagesFromContent(dto.getContent());
                //2.图片数量大于等于3设置为多图，数量在1-3之间设置为单独；数量为空设置为无图
                if (CollectionUtils.isEmpty(contentImages)) {
                    //无图
                    wmNews.setImages("");
                    wmNews.setType(MediaEnum.NEWS_COVER_TYPE_MANY.getVal());
                }
                if (contentImages.size() >= 3) {
                    List<ImageDto> imageDtoList = contentImages.subList(0, 3);
                    String coverImage = imageDtoList.stream().map(ImageDto::getUrl).collect(Collectors.joining(","));
                    wmNews.setImages(coverImage);
                    wmNews.setType(MediaEnum.NEWS_COVER_TYPE_MANY.getVal());
                } else {
                    ImageDto imageDto = contentImages.get(0);
                    wmNews.setImages(imageDto.getUrl());
                    wmNews.setType(MediaEnum.NEWS_COVER_TYPE_ONE.getVal());
                }
                break;
        }
    }


    /**
     * 从文章正文中获取图片
     *
     * @param content 文章正文
     *                content: "[{\"type\":\"text\",\"value\":\"第一段内容\\n\"},{\"type\":\"image\",\"value\":\"http://192.168.137.136:9000/leadnews/0edb5264-a033-4a47-a586-43a51b4ce73a.png\",\"id\":120}]
     * @return
     */
    private List<ImageDto> getImagesFromContent(String content) {
        //1.采用FastJSON转换  将字符串转为java对象 String---->ContentDTO
        List<ContentDto> contentDtos = JSON.parseArray(content, ContentDto.class);
        //2.遍历段落集合 获取图片
        if (!CollectionUtils.isEmpty(contentDtos)) {
            List<ImageDto> imageDtos = new ArrayList<>();
            for (ContentDto contentDto : contentDtos) {
                if ("image".equals(contentDto.getType())) {
                    ImageDto imageDto = new ImageDto();
                    imageDto.setId(contentDto.getId());
                    imageDto.setUrl(contentDto.getValue());
                    imageDtos.add(imageDto);
                }
            }
            return imageDtos;
        }
        return null;
    }


    /**
     * 更新自媒体文章上下架状态；异步更新发布库文章状态
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNews dto) {
        //1.根据自媒体文章ID查询文章记录-判断状态
        WmNews wmNews = this.getById(dto.getId());
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        if (!wmNews.getStatus().equals(MediaEnum.NEWS_SUBMIT_STATUS_PUBLISH.getVal())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }
        //2.修改自媒体文章状态
        wmNews.setEnable(dto.getEnable());
        this.updateById(wmNews);

        //3.发送消息到Kafka中
        HashMap<String, Object> map = new HashMap<>();
        map.put("articleId", wmNews.getArticleId());
        map.put("isDown", !dto.getEnable());
        kafkaTemplate.send(upDownTopic, JSON.toJSONString(map));
        return ResponseResult.okResult();
    }
}
